﻿#include "comport.h"
#include <QDebug>
#include <QThread>

//-----------------------------------------------------------------------------------------------------

ComPort::ComPort(QObject *parent) :
    QObject(parent),
    m_pSerialport(NULL),
    m_running(0),
    m_pReadTimer(NULL)
{
    m_pReadTimer = new QTimer(this);
    m_pReadTimer->setInterval(20);
    connect(m_pReadTimer, SIGNAL(timeout()), this, SLOT(getDataFromPort()));
}

ComPort::~ComPort()
{
    m_pReadTimer->stop();
    delete m_pReadTimer;

    if (m_pSerialport != NULL)
    {
        m_pSerialport->close();
        delete m_pSerialport;
        m_pSerialport = NULL;
    }
}

void ComPort::setComPortName(QString portName)
{
    m_portName.clear();

    if(portName.length() > 0)//串口名称不为空
    {
        m_portName = portName;
        return;
    }

    //windows平台下
#ifdef Q_OS_WIN
    //得到串口设备
    QString path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM";
    QSettings *settings = new QSettings(path,QSettings::NativeFormat);
    QStringList key = settings->allKeys();
    int num = (int)key.size();

    //打开注册表
    unsigned long keysize,type,valuesize;
    wchar_t keyname[256]; //键名数组
    char keyvalue[256];  //键值数组
    keysize = sizeof(keyname);
    valuesize = sizeof(keyvalue);
    int indexnum;
    HKEY hKey;
    QString commresult = "";
    QString valuemessage = "";//键值
    QString strkey = "HARDWARE\\DEVICEMAP\\SERIALCOMM";//子键路径
    LPCWSTR subkey = reinterpret_cast<const wchar_t *>(strkey.utf16());

    if(::RegOpenKeyEx(HKEY_LOCAL_MACHINE,subkey,0,KEY_READ,&hKey)!=0)
    {
        return;
    }

    //循环得到串口设备的名称
    for(int i = 0; i < num; i++)
    {
        valuemessage.clear();
        commresult.clear();
        keysize=sizeof(keyname);
        valuesize=sizeof(keyvalue);
        indexnum=i;//要读取键值的索引号

        if(::RegEnumValue(hKey,indexnum,keyname,&keysize,0,&type,(BYTE*)keyvalue,&valuesize) == 0)//列举键名和值
        {
            for(unsigned int j = 0; j < valuesize; j++)
            {
                if(keyvalue[j]!=0x00)
                {
                    valuemessage.append(keyvalue[j]);
                }
            }
            if(m_portName.length() <= 0)
            {
                m_portName = valuemessage;
            }
        }
        else
        {
            commresult="nokey";
        }
    }
    ::RegCloseKey(hKey);//关闭注册表
#endif

#ifdef Q_OS_LINUX
    m_portName = COMNAME;
#endif
    return;
}

void ComPort::initComm()
{
    if (m_running == 0)
    {
        qDebug() << "InitComm ComPort at thread" << QThread::currentThread() << "name" << m_portName;

        struct PortSettings myComSetting = {BAUD115200, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 0, 20};
        m_pSerialport = new QextSerialPort(m_portName, myComSetting);
        bool bOpen = m_pSerialport->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
        if(bOpen == false)
        {
            emit siSerialPortOpenState(m_running);
            qDebug()<<"m_pSerialport->open fail ";
            return;
        }else
        {
            qDebug()<<"m_pSerialport->open success ";
        }

        qDebug() << "Start timer";

        m_pReadTimer->start();
        m_running = 1;
        emit siSerialPortOpenState(m_running);
    }
}

void ComPort::getDataFromPort()
{
//    qDebug("GetDataFromPort");
//    qDebug() << "ComPort GetDataFromPort" << QThread::currentThread();

    if (m_running != 0 && m_pSerialport != NULL)
    {
        QByteArray dat = m_pSerialport->readAll();
        if (dat.size() != 0)
        {
            //qDebug()<<"dat.size()="<<dat.size();
            qDebug()<< "m_pSerialport->readAll() :"<<dat.data();
            emit (siReceiveData(dat));
        }
    }
}

void ComPort::slotSendData(QByteArray dat)
{
//    qDebug() << "ComPort SlotSendData" << QThread::currentThread();

    if (m_running != 0 && m_pSerialport != NULL && dat.size() != 0)
    {
        qDebug()<<"ComPort::slotSendData send data" << QString(dat);
        m_pSerialport->write(dat.data(), dat.size());
    }
}
